package helper.scxml.scxml2

import helper.base.list.DoubleList
import helper.base.list.DoubleListList
import helper.scxml.scxml2.MathHelper.DSSUnit.Expand.toArray2DRowRealMatrix
import helper.scxml.scxml2.MathHelper.DoubleArrayListExpand.toArrayRealVector
import org.apache.commons.math3.linear.LUDecomposition
import kotlin.math.pow
import kotlin.math.sqrt

object DistanceHelper {
    //差方和后，开根号
    fun getEuclideanDistance(
        v: List<Double>,
        other: List<Double>,
    ): Double {
        val squaredDifferences = v.zip(
            other
        ) { a, b ->
            (a - b).pow(2.0)
        }
        val sumOfSquaredDifferences = squaredDifferences.sum()
        return sqrt(
            sumOfSquaredDifferences
        )
    }

    fun getDistanceToMatrix(
        ds: DoubleList, mean: DoubleList, matrix: DoubleListList
    ): Double {
        val u = ds.toArrayRealVector()
        val v = mean.toArrayRealVector()
        val q = matrix.toArray2DRowRealMatrix()

        // 计算矩阵 Q 的逆矩阵 Q^{-1}
        val luDecomposition = LUDecomposition(q)
        val qInverse = luDecomposition.solver.inverse

        // 计算 (u-\bar{v})^{T} Q^{-1}(u-\bar{v})
        val diff = u.subtract(v)
        val result = diff.dotProduct(
            qInverse.operate(diff)
        )

        return sqrt(result)
    }

    fun getWeightFromDistance(
        aN: Int,
        distance: Double,
    ): Double {
        return aN * Math.E.pow(
            -distance
        )
    }
}